package com.andy.blog.admin.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.andy.blog.admin.dto.BlogInfoDTO;
import com.andy.blog.admin.dto.SiteConfig;
import com.andy.blog.admin.service.BlogInfoBusService;
import com.andy.blog.admin.service.ConfigBusService;
import com.andy.blog.common.constant.BlogInfoConstants;
import com.andy.blog.common.constant.CacheConstants;
import com.andy.blog.common.core.redis.RedisCache;
import com.andy.blog.common.enums.AlbumPhotoEnum;
import com.andy.blog.common.exception.BlogServiceException;
import com.andy.blog.common.reponse.BlogResultCode;
import com.andy.blog.common.utils.SystemInfoUtils;
import com.andy.blog.common.utils.http.OkHttpUtils;
import com.andy.blog.common.utils.ip.IpUtils;
import com.andy.blog.dal.domain.AlbumPhotoDO;
import com.andy.blog.dal.service.AlbumPhotoDalService;
import com.andy.blog.dal.service.ArticleDalService;
import com.andy.blog.dal.service.CategoryDalService;
import com.andy.blog.dal.service.HitokotoDalService;
import com.andy.blog.dal.service.TagDalService;
import com.andy.blog.dal.vo.AlbumPhotoVO;
import com.andy.blog.dal.vo.ArticleVO;
import com.andy.blog.dal.vo.CategoryVO;
import com.andy.blog.dal.vo.HitokotoVO;
import com.andy.blog.dal.vo.TagVO;
import com.andy.blog.framework.manager.AsyncManager;
import com.andy.blog.framework.manager.factory.AsyncFactory;
import io.vavr.Tuple5;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created by andy on 2023/8/5 10:30
 */
@Service
public class BlogInfoBusServiceImpl implements BlogInfoBusService {

    private final static Logger log = LoggerFactory.getLogger(BlogInfoBusServiceImpl.class);

    @Resource
    private RedisCache redisCache;

    @Resource
    private ConfigBusService configBusService;

    @Resource
    private TagDalService tagDalService;

    @Resource
    private ArticleDalService articleDalService;

    @Resource
    private CategoryDalService categoryDalService;

    @Resource
    private AlbumPhotoDalService albumPhotoDalService;

    @Resource
    private HitokotoDalService hitokotoDalService;


    @Override
    public void report() {
        // 获取用户ip
        String ipAddress = IpUtils.getIpAddress();

        Tuple5<String, String, String, String, String> sysInfo = SystemInfoUtils.getSysInfo();

        // 获取访问设备
        String browser = sysInfo._1;
        String os = sysInfo._2;
        // 生成唯一用户标识
        String uuid = ipAddress + browser + os;
        String md5 = DigestUtils.md5DigestAsHex(uuid.getBytes());
        // 判断是否访问
        if (Boolean.FALSE.equals(redisCache.hasSetValue(BlogInfoConstants.UNIQUE_VISITOR, md5))) {
            // 访问量+1
            redisCache.incr(BlogInfoConstants.BLOG_VIEW_COUNT, 1);
            // 保存唯一标识
            redisCache.setSet(BlogInfoConstants.UNIQUE_VISITOR, md5);
        }
    }

    @Override
    public BlogInfoDTO getBlogInfo() {

        BlogInfoDTO cacheObject = redisCache.getCacheObject(CacheConstants.BLOG_INFO_CACHE);
        if (Objects.nonNull(cacheObject)) {
            return cacheObject;
        }

        // 文章条数
        Long articleCount = articleDalService.selectArticleCount(ArticleVO.builder().build());
        // 标签数
        Long tagCount = tagDalService.selectTagCount(TagVO.builder().build());
        // 分类数
        Long categoryCount = categoryDalService.selectCategoryCount(CategoryVO.builder().build());
        // 博客访问量
        Integer viewCount = redisCache.getCacheObject(BlogInfoConstants.BLOG_VIEW_COUNT);

        CompletableFuture<SiteConfig> siteConfigCompletableFuture = CompletableFuture.supplyAsync(() -> {
            SiteConfig siteConfig = new SiteConfig();
            siteConfig.setId(1L);
            siteConfig.setUserAvatar("http://s1qmuvqoq.bkt.clouddn.com/20230826/0bd6d585ee824573b2bad9fe9a7d499e16881740715993528.jpg");
            siteConfig.setTouristAvatar(configBusService.selectConfigByKey("portal.tourist.avatar"));
            siteConfig.setSiteName(configBusService.selectConfigByKey("portal.site.name"));
            siteConfig.setSiteAddress("https://www.ttkwsd.top");
            siteConfig.setSiteIntro("上善若水");
            siteConfig.setSiteNotice("后端基于SpringBoot开发，前端基于Vue3 Ts Navie UI开发，<a href=\\\"https://gitee.com/wu_shengdong/blog\\\" style=\\\"color: #49b1f5;\\\">网站源码</a>");
            siteConfig.setCreateSiteTime(configBusService.selectConfigByKey("CREATE_SITE_TIME"));
            siteConfig.setFilingNumber(configBusService.selectConfigByKey("portal.filing.number"));
            siteConfig.setAuthorAvatar(configBusService.selectConfigByKey("portal.author.avatar"));
            siteConfig.setSiteAuthor(configBusService.selectConfigByKey("SITE_AUTHOR"));
            siteConfig.setArticleCover("http://s1qmuvqoq.bkt.clouddn.com/20230902/d6a00d059a1e9729e763469deb4870df.jpg");
            siteConfig.setAboutMe("");
            siteConfig.setGithub("");
            siteConfig.setGitee(configBusService.selectConfigByKey("portal.site.gitee"));
            siteConfig.setBilibili(configBusService.selectConfigByKey("BILIBILI"));
            siteConfig.setQq(configBusService.selectConfigByKey("QQ"));
            siteConfig.setCommentCheck(0);
            siteConfig.setMessageCheck(0);
            siteConfig.setIsReward(0);
            siteConfig.setWeiXinCode("");
            siteConfig.setAliCode("");
            siteConfig.setEmailNotice(1);
            siteConfig.setSocialList("gitee,bilibili,github,qq");
            siteConfig.setLoginList("gitee,github");
            return siteConfig;
        });

        CompletableFuture<List<AlbumPhotoDO>> completableFuture = CompletableFuture.supplyAsync(() -> {
            // 相册信息
            List<AlbumPhotoDO> albumPhotoDOS = albumPhotoDalService.selectList(AlbumPhotoVO.builder().typeList(AlbumPhotoEnum.getCodeList()).build());

            return albumPhotoDOS.stream().filter(s -> !Objects.equals(0L, s.getParentId())).collect(Collectors.toList());
        });

        CompletableFuture<BlogInfoDTO> combinedResultFuture = CompletableFuture.allOf(siteConfigCompletableFuture, completableFuture)
                .thenApplyAsync((voidResult) -> {
                    // 获取已完成的future的结果
                    BlogInfoDTO blogInfoDTO = new BlogInfoDTO();
                    blogInfoDTO.setArticleCount(articleCount);
                    blogInfoDTO.setTagCount(tagCount);
                    blogInfoDTO.setCategoryCount(categoryCount);
                    blogInfoDTO.setViewCount(Optional.ofNullable(viewCount).orElse(0));
                    blogInfoDTO.setSiteConfig(siteConfigCompletableFuture.join());
                    blogInfoDTO.setPhotoDTOList(completableFuture.join());
                    return blogInfoDTO;
                });

        redisCache.setCacheObject(CacheConstants.BLOG_INFO_CACHE, combinedResultFuture.join(), 3, TimeUnit.MINUTES);

        return combinedResultFuture.join();
    }

    @Override
    public String getEveryHitokoto() {

        String cacheObject = redisCache.getCacheObject(CacheConstants.BLOG_HITOKOTO_CACHE);
        if (StringUtils.isNotBlank(cacheObject)) {
            return cacheObject;
        }

        String url = configBusService.selectConfigByKey("portal.hitokoto");

        String result;
        try {
            result = OkHttpUtils.sendGet(url);
        } catch (IOException e) {
            log.error("获取每日一言失败，使用默认值", e);
            throw new BlogServiceException(BlogResultCode.BLOG_000010);
        }

        if (StringUtils.isBlank(result)) {

            return null;
        }

        JSONObject jsonObject = JSON.parseObject(result);
        String hitokoto = jsonObject.getString("hitokoto");

        if (StringUtils.isBlank(hitokoto)) {
            return getHitokotoRandom();
        }

        redisCache.setCacheObject(CacheConstants.BLOG_HITOKOTO_CACHE, hitokoto, 1, TimeUnit.MINUTES);

        HitokotoVO hitokotoVO = new HitokotoVO();
        hitokotoVO.setContent(hitokoto);
        AsyncManager.me().execute(AsyncFactory.addHitokoto(hitokotoVO));

        return hitokoto;
    }


    private String getHitokotoRandom() {
        HitokotoVO hitokotoVO = hitokotoDalService.selectDataByRandom();
        return hitokotoVO.getContent();
    }
}
